package com.nullam.lorem.contactsync.data;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;

public class ContactReader {
	private Activity activity;
	private static final String[] PHOTO_ID_PROJECTION = new String[] { ContactsContract.Contacts.PHOTO_ID };

	private static final String[] PHOTO_BITMAP_PROJECTION = new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO };

	public ContactReader(Activity activity) {
		this.activity = activity;
	}

	/**
	 * @author Nhat Thuy
	 * @return contacts includes contacts in SIM, Phone, Google Account...
	 */
	public List<Contact> fetchContacts() {
		ArrayList<Contact> contacts = new ArrayList<Contact>();

		Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
		String _ID = ContactsContract.Contacts._ID;
		String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;

		String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;

		Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
		String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
		String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
		String NUMBER_TYPE = ContactsContract.CommonDataKinds.Phone.TYPE;

		Uri EmailCONTENT_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
		String EmailCONTACT_ID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
		String EMAIL = ContactsContract.CommonDataKinds.Email.DATA;
		String EMAIL_TYPE = ContactsContract.CommonDataKinds.Email.TYPE;

		ContentResolver contentResolver = activity.getContentResolver();

		Cursor cursor = contentResolver.query(CONTENT_URI, null, null, null,
				null);

		// Loop for every contact in the phone
		if (cursor.getCount() > 0) {
			while (cursor.moveToNext()) {
				String contactId = cursor.getString(cursor.getColumnIndex(_ID));
				long contactIdLong = Long.parseLong(contactId);
				String name = cursor.getString(cursor
						.getColumnIndex(DISPLAY_NAME));
				int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor
						.getColumnIndex(HAS_PHONE_NUMBER)));
				Contact contact = new Contact();
				contact.setContactId(contactIdLong);
				contact.setDisplayName(name);
				contact.setPhotoId(loadContactPhoto(contentResolver,
						contactIdLong));
				if (hasPhoneNumber > 0 && name.length() > 0) {
					// Query and loop for every phone number of the contact
					Cursor phoneCursor = contentResolver.query(
							PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?",
							new String[] { contactId }, null);
					int phoneTypeInt;
					String phoneType;
					String phoneNumber = null;
					HashMap<String, String> phoneNumbers = new HashMap<String, String>();
					while (phoneCursor.moveToNext()) {
						phoneNumber = phoneCursor.getString(phoneCursor
								.getColumnIndex(NUMBER));
						phoneTypeInt = phoneCursor.getInt(phoneCursor
								.getColumnIndex(NUMBER_TYPE));
						phoneType = (String) Phone.getTypeLabel(
								activity.getResources(), phoneTypeInt, "");
						phoneNumbers.put(phoneNumber, phoneType);
					}
					contact.setPhoneNumbers(phoneNumbers);
					phoneCursor.close();

				}
				// Query and loop for every email of the contact
				Cursor emailCursor = contentResolver.query(EmailCONTENT_URI,
						null, EmailCONTACT_ID + " = ?",
						new String[] { contactId }, null);
				String email = null;
				int emailTypeInt;
				String emailType = null;
				HashMap<String, String> emails = new HashMap<String, String>();
				while (emailCursor.moveToNext()) {
					email = emailCursor.getString(emailCursor
							.getColumnIndex(EMAIL));
					emailTypeInt = emailCursor.getInt(emailCursor
							.getColumnIndex(EMAIL_TYPE));
					emailType = (String) Email.getTypeLabel(
							activity.getResources(), emailTypeInt, "");
					emails.put(email, emailType);
					contact.setEmails(emails);
				}
				emailCursor.close();
				contacts.add(contact);
			}
		}
		return contacts;
	}

	/**
	 * @author Nhat Thuy
	 * @param contactId
	 * @return Retrieving the thumbnail-sized photo
	 */
	public InputStream openPhoto(long contactId) {
		Uri contactUri = ContentUris.withAppendedId(
				ContactsContract.Contacts.CONTENT_URI, contactId);

		Uri photoUri = Uri.withAppendedPath(contactUri,
				ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
		Cursor cursor = activity.getContentResolver().query(photoUri,
				new String[] { ContactsContract.Contacts.Photo.PHOTO }, null,
				null, null);
		if (cursor == null) {
			return null;
		}
		try {
			if (cursor.moveToFirst()) {
				byte[] data = cursor.getBlob(0);
				if (data != null) {
					return new ByteArrayInputStream(data);
				}
			}
		} finally {
			cursor.close();
		}
		return null;
	}

	/**
	 * @author Nhat Thuy
	 * @param contactId
	 * @return Retrieving the larger photo version
	 */
	public InputStream openDisplayPhoto(long contactId) {
		Uri contactUri = ContentUris.withAppendedId(
				ContactsContract.Contacts.CONTENT_URI, contactId);
		Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
				ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
		try {
			AssetFileDescriptor fd = activity.getContentResolver()
					.openAssetFileDescriptor(displayPhotoUri, "r");
			return fd.createInputStream();
		} catch (IOException e) {
			return null;
		}
	}

	public static Bitmap loadContactPhoto(ContentResolver cr, long id) {
		Uri uri = ContentUris.withAppendedId(
				ContactsContract.Contacts.CONTENT_URI, id);
		InputStream input = ContactsContract.Contacts
				.openContactPhotoInputStream(cr, uri);
		if (input == null) {
			return null;
		}
		try {
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return BitmapFactory.decodeStream(input);
	}

}
